/*
 * 描          述:  <描述>
 * 修  改   人:  Administrator
 * 修改时间:  2018年5月3日
 * <修改描述:>
 */
package com.tx.component.task.starter;

import javax.sql.DataSource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.transaction.PlatformTransactionManager;

import com.tx.component.dailytask.configuration.DailyTaskContextConfiguration;
import com.tx.component.task.TaskContextConstants;
import com.tx.component.task.context.TaskContextFactory;
import com.tx.component.task.interceptor.TaskExecuteInterceptorFactory;
import com.tx.component.task.interceptor.TaskInterceptorBeanPostProcessor;
import com.tx.component.task.service.TaskContextRegistry;
import com.tx.component.task.service.TaskDefService;
import com.tx.component.task.service.TaskDetailService;
import com.tx.component.task.service.TaskExecuteLogService;
import com.tx.component.task.service.TaskStatusService;
import com.tx.core.exceptions.util.AssertUtils;
import com.tx.core.starter.component.ComponentSupportAutoConfiguration;
import com.tx.core.util.SignatureUtils;

/**
 * 任务容器自动配置类<br/>
 * <功能详细描述>
 * 
 * @author  Administrator
 * @version  [版本号, 2018年5月3日]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
@Configuration
@AutoConfigureAfter({ ComponentSupportAutoConfiguration.class })
@EnableConfigurationProperties(TaskContextProperties.class)
@ConditionalOnClass({ TaskContextFactory.class })
@ConditionalOnSingleCandidate(DataSource.class)
@ConditionalOnBean(PlatformTransactionManager.class)
@ConditionalOnProperty(prefix = TaskContextConstants.PROPERTIES_PREFIX, value = "enable", havingValue = "true")
@Import({ ImportTaskContextConfiguration.class,
        DailyTaskContextConfiguration.class })
public class TaskContextAutoConfiguration
        implements InitializingBean, ApplicationContextAware {
    
    protected ApplicationContext applicationContext;
    
    /** 任务容器属性 */
    private TaskContextProperties properties;
    
    /** 当前容器签名 */
    private String signature;
    
    /** 容器所属模块：当该值为空时，使用spring.application.name的内容 */
    private String module;
    
    /** application.name */
    @Value(value = "${spring.application.name}")
    private String applicationName;
    
    /** 事务管理器 */
    private PlatformTransactionManager transactionManager;
    
    /** <默认构造函数> */
    public TaskContextAutoConfiguration(TaskContextProperties properties,
            PlatformTransactionManager transactionManager) {
        super();
        this.properties = properties;
        this.transactionManager = transactionManager;
    }
    
    /**
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        this.applicationContext = applicationContext;
    }
    
    /**
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        //初始化包名
        if (!StringUtils.isBlank(this.applicationName)) {
            this.module = this.applicationName;
        }
        if (!StringUtils.isEmpty(this.properties.getModule())) {
            this.module = this.properties.getModule();
        }
        AssertUtils.notEmpty(this.module, "module is empty.");
        
        // 生成服务签名（ip信息 + classpath信息）
        this.signature = String.valueOf(
                Math.abs(SignatureUtils.generateSignature().hashCode()));
    }
    
    /**
     * 任务执行拦截器<br/>
     * <功能详细描述>
     * @param taskDefService
     * @param taskStatusService
     * @param taskExecuteLogService
     * @return [参数说明]
     * 
     * @return TaskExecuteInterceptor [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     */
    @Bean("task.taskExecuteInterceptorFactory")
    public TaskExecuteInterceptorFactory TaskExecuteInterceptorFactory(
            TaskDefService taskDefService, TaskStatusService taskStatusService,
            TaskExecuteLogService taskExecuteLogService) {
        TaskExecuteInterceptorFactory facotry = new TaskExecuteInterceptorFactory();
        facotry.setSignature(this.signature);
        facotry.setTransactionManager(this.transactionManager);
        facotry.setTaskDefService(taskDefService);
        facotry.setTaskStatusService(taskStatusService);
        facotry.setTaskExecuteLogService(taskExecuteLogService);
        return facotry;
    }
    
    /**
     * 任务烂机器注入的PostProcessor实现<br/>
     * <功能详细描述>
     * @param registry
     * @param interceptor
     * @return [参数说明]
     * 
     * @return TaskInterceptorBeanPostProcessor [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     */
    @Bean("task.taskInterceptorBeanPostProcessor")
    public TaskInterceptorBeanPostProcessor taskInterceptorBeanPostProcessor(
            TaskContextRegistry registry,
            TaskExecuteInterceptorFactory interceptorFactory) {
        TaskInterceptorBeanPostProcessor processor = new TaskInterceptorBeanPostProcessor();
        processor.setModule(this.module);
        processor.setSignature(this.signature);
        processor.setRegistry(registry);
        processor.setInterceptorFactory(interceptorFactory);
        return processor;
    }
    
    /**
     * 注入任务容器工厂<br/>
     * <功能详细描述>
     * @param taskDefService
     * @param taskStatusService
     * @param taskExecuteLogService
     * @param taskDetailService
     * @return [参数说明]
     * 
     * @return TaskContextFactory [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     */
    @Bean("task.TaskContextFactory")
    public TaskContextFactory taskContext(TaskDefService taskDefService,
            TaskStatusService taskStatusService,
            TaskExecuteLogService taskExecuteLogService,
            TaskDetailService taskDetailService) {
        TaskContextFactory factory = new TaskContextFactory();
        factory.setTaskDefService(taskDefService);
        factory.setTaskStatusService(taskStatusService);
        factory.setTaskExecuteLogService(taskExecuteLogService);
        factory.setTaskDetailService(taskDetailService);
        return factory;
    }
    
}
